import { resolveAllImports, hasImports, findAndRemoveImports, getPageMetadataAndSlug, topologicalSort, } from '@mintlify/common';
import { outputFile } from 'fs-extra';
import { join } from 'path';
export class ImportResolver {
    constructor(contentDirectoryPath, openApiFiles, pagesAcc, snippetsV2, filesWithImports) {
        this.contentDirectoryPath = contentDirectoryPath;
        this.openApiFiles = openApiFiles;
        this.pagesAcc = pagesAcc;
        this.snippetsV2 = snippetsV2;
        this.filesWithImports = filesWithImports;
    }
    static writeFiles(updateOrchestrator, pagesAcc, snippetsV2, filesWithImports) {
        return new ImportResolver(updateOrchestrator.contentDirectoryPath, updateOrchestrator.openApiFiles, pagesAcc, snippetsV2, filesWithImports).writeFiles();
    }
    async writeFiles() {
        const snippetsWithResolvedImports = await this.resolveImportsInSnippets();
        const writeSnippetsWithImportsPromises = this.writeSnippets(snippetsWithResolvedImports);
        const pagesWithResolvedImports = await this.resolveImportsInPages(snippetsWithResolvedImports);
        const writePagesPromise = this.writePages(pagesWithResolvedImports);
        await Promise.all([...writeSnippetsWithImportsPromises, ...writePagesPromise]);
        return this.pagesAcc;
    }
    async resolveImportsInSnippets() {
        const snippetsWithImportsPromises = this.snippetsV2.map(async (snippet) => ({
            ...(await findAndRemoveImports(snippet.content)),
            filename: snippet.filename,
        }));
        const snippetsWithImports = await Promise.all(snippetsWithImportsPromises);
        const graph = {};
        snippetsWithImports.forEach((snippetWithImports) => {
            graph[snippetWithImports.filename] = Object.keys(snippetWithImports.importMap);
        });
        const order = topologicalSort(graph).reverse();
        const orderedSnippetsWithImports = order
            .map((filename) => {
            return snippetsWithImports.find((snippet) => snippet.filename === filename);
        })
            .filter(Boolean);
        for (const snippetWithImports of orderedSnippetsWithImports) {
            if (hasImports(snippetWithImports)) {
                snippetWithImports.content = await resolveAllImports({
                    snippets: orderedSnippetsWithImports,
                    fileWithImports: snippetWithImports,
                });
            }
        }
        return snippetsWithImports;
    }
    writeSnippets(snippetsWithImports) {
        return snippetsWithImports.map(async (snippetWithImports) => {
            const targetPath = join('public', snippetWithImports.filename);
            await outputFile(targetPath, snippetWithImports.content, {
                flag: 'w',
            });
        });
    }
    async resolveImportsInPages(snippets) {
        const filesWithResolvedImportsPromises = this.filesWithImports.map(async (fileWithImports) => {
            const content = await resolveAllImports({
                snippets,
                fileWithImports,
            });
            const { slug, pageMetadata } = getPageMetadataAndSlug(fileWithImports.filename, content, this.openApiFiles);
            this.pagesAcc = {
                ...this.pagesAcc,
                [slug]: pageMetadata,
            };
            const targetPath = join('src', '_props', fileWithImports.filename);
            return {
                targetPath,
                content,
            };
        });
        return await Promise.all(filesWithResolvedImportsPromises);
    }
    writePages(filesWithResolvedImports) {
        return filesWithResolvedImports.map(async ({ targetPath, content }) => {
            await outputFile(targetPath, content, {
                flag: 'w',
            });
        });
    }
}
